<script lang="ts" setup>
import {
  ElMessageBox,
  ElDialog,
  ElButton,
  ElForm,
  ElFormItem,
  ElInput,
  ElInputNumber,
  ElRadioGroup,
  ElRadio,
  ElMessage,
  ElTreeSelect,
  ElTree,
} from "element-plus";
import { nextTick, reactive, ref } from "vue";
import { edit, add, getRoleById } from "#/api/sys/role";
import { getMenuList, listAll, getMenusByModuleType } from "#/api/sys/menu";

const dialogVisible = ref(false);
const title = ref("添加角色");
// 添加全选相关的响应式变量和方法
const isAllChecked = ref(false);
// 添加全选节点数据
const selectAllNode = ref({
  id: "select-all",
  menuName: "全选",
  children: [],
});

const spaceInput = (field: string, value: string) => {
  // 过滤空格
  ruleForm[field] = value.replace(/\s+/g, "");
};

const useForm = () => {
  const formRef = ref();
  const reset = async () => {
    await nextTick();
    formRef.value?.resetFields();
  };
  return { formRef, reset };
};
const { formRef: ruleFormRef, reset } = useForm();
const addDialog = () => {
  dialogVisible.value = true;
  title.value = "添加角色";
  reset();
  resetChecked();
  getTableData();
  nextTick(() => {
    if (treeRef.value) {
      treeRef.value.setCheckedKeys([], false);
    }
    isAllChecked.value = false;
  });
};

// 修改 editDialog 方法
const editDialog = (obj) => {
  dialogVisible.value = true;
  title.value = "编辑角色";
  ruleForm.id = obj.id;
  getDetail(obj.id);
  getTableData();
  nextTick(() => {
    if (treeRef.value) {
      // 处理编辑时的选中状态
      const menuIds = ruleForm.menuIds || [];
      const allDataKeys = getAllNodeKeys(
        treeRoleData.value.filter((node) => node.id !== "select-all")
      );
      const isAllSelected =
        menuIds.length === allDataKeys.length && allDataKeys.length > 0;

      if (isAllSelected && allDataKeys.length > 0) {
        treeRef.value.setCheckedKeys(["select-all", ...menuIds]);
      } else {
        treeRef.value.setCheckedKeys(menuIds);
      }

      isAllChecked.value = isAllSelected;
    }
  });
};

defineExpose({ addDialog, editDialog });
const emit = defineEmits(["search"]);

// 修改全选/取消全选功能
const toggleSelectAll = () => {
  if (!treeRef.value) return;

  if (isAllChecked.value) {
    // 当前是全选状态，执行取消全选
    treeRef.value.setCheckedKeys([]);
    isAllChecked.value = false;
  } else {
    // 当前不是全选状态，执行全选
    const allKeys = getAllNodeKeys(
      treeRoleData.value.filter((node) => node.id !== "select-all")
    );
    treeRef.value.setCheckedKeys(["select-all", ...allKeys]);
    isAllChecked.value = true;
  }
};

// 获取所有节点的key（包括父子节点）
const getAllNodeKeys = (nodes) => {
  let keys = [];
  nodes.forEach((node) => {
    // 跳过全选节点
    if (node.id === "select-all") return;

    keys.push(node.id);
    if (node.children && node.children.length > 0) {
      keys = keys.concat(getAllNodeKeys(node.children));
    }
  });
  return keys;
};

// 修改节点选择处理逻辑
const handleCheckChange = (data, checkedInfo) => {
  if (!treeRef.value) return;

  // 如果是全选节点被选中/取消选中
  if (data.id === "select-all") {
    if (checkedInfo.checkedKeys.includes("select-all")) {
      // 全选节点被选中，执行全选
      const allKeys = getAllNodeKeys(
        treeRoleData.value.filter((node) => node.id !== "select-all")
      );
      treeRef.value.setCheckedKeys(["select-all", ...allKeys]);
      isAllChecked.value = true;
    } else {
      // 全选节点被取消选中，执行取消全选
      treeRef.value.setCheckedKeys([]);
      isAllChecked.value = false;
    }
    return;
  }

  // 处理普通节点选择变化
  nextTick(() => {
    const checkedKeys = treeRef.value.getCheckedKeys();
    const allDataKeys = getAllNodeKeys(
      treeRoleData.value.filter((node) => node.id !== "select-all")
    );

    // 检查是否所有普通节点都被选中
    const nonSelectAllCheckedKeys = checkedKeys.filter(
      (key) => key !== "select-all"
    );
    const isFullySelected =
      nonSelectAllCheckedKeys.length === allDataKeys.length &&
      allDataKeys.length > 0;

    // 根据是否全选来决定是否选中全选节点
    if (isFullySelected) {
      // 所有普通节点都选中，自动选中全选节点
      if (!checkedKeys.includes("select-all")) {
        treeRef.value.setCheckedKeys(["select-all", ...nonSelectAllCheckedKeys]);
      }
      isAllChecked.value = true;
    } else {
      // 有节点未选中，自动取消全选节点
      if (checkedKeys.includes("select-all")) {
        treeRef.value.setCheckedKeys(nonSelectAllCheckedKeys);
      }
      isAllChecked.value = false;
    }
  });
};

const getDetail = async (id) => {
  const params = {
    id: id,
  };
  const { data } = await getRoleById(params);
  ruleForm.roleName = data.roleName;
  ruleForm.status = data.status + "";
  ruleForm.sort = data.sort;
  ruleForm.menuIds = data.menuIds;
  ruleForm.roleValue = data.roleValue;

  // 设置选中状态时排除全选节点的处理
  nextTick(() => {
    if (treeRef.value) {
      const menuIds = data.menuIds || [];
      const allDataKeys = getAllNodeKeys(
        treeRoleData.value.filter((node) => node.id !== "select-all")
      );
      const isAllSelected =
        menuIds.length === allDataKeys.length && allDataKeys.length > 0;

      if (isAllSelected && allDataKeys.length > 0) {
        treeRef.value.setCheckedKeys(["select-all", ...menuIds]);
      } else {
        treeRef.value.setCheckedKeys(menuIds);
      }

      isAllChecked.value = isAllSelected;
    }
  });
};

const ruleForm = reactive<RuleForm>({
  id: "",
  roleName: "",
  roleValue: "",
  sort: 1,
  status: "1",
  menuIds: [],
});

const rules = reactive({
  roleName: [
    { required: true, message: "请输入角色名称", trigger: "blur" },
    { min: 1, max: 20, message: "请输入最多20字", trigger: "blur" },
  ],
  roleValue: [
    { required: true, message: "请输入角色标识", trigger: "blur" },
    { min: 1, max: 20, message: "请输入最多20字", trigger: "blur" },
  ],
  sort: [{ required: true, message: "请输入排序号", trigger: "blur" }],
  status: [{ required: true, message: "请选择状态", trigger: "change" }],
  menuIds: [{ required: true, message: "请选择权限", trigger: "change" }],
});
const treeRoleData = ref([]);
const treeRef = ref();

const defaultProps = {
  children: "children",
  label: "menuName",
};

const loading = ref(false);

const addForm = () => handleSubmit(false);
const editForm = () => handleSubmit(true);

const buildFormParams = (isEdit: boolean) => ({
  ...(isEdit && { id: ruleForm.id }),
  status: ruleForm.status,
  roleName: ruleForm.roleName,
  sort: ruleForm.sort,
  menuIds: ruleForm.menuIds,
  roleValue: ruleForm.roleValue,
});

const handleApiResponse = (isEdit: boolean) => {
  ElMessage.success(isEdit ? "修改成功" : "添加成功");
  emit("search");
  dialogVisible.value = false;
};

const submitForm = async (isEdit = false) => {
  if (loading.value) return;

  try {
    loading.value = true;
    // 获取选中的节点，排除全选节点
    const checkedKeys = treeRef.value.getCheckedKeys();
    ruleForm.menuIds = checkedKeys.filter((key) => key !== "select-all");

    await ruleFormRef.value?.validate();

    const params = buildFormParams(isEdit);
    const { code, msg } = isEdit ? await edit(params) : await add(params);
    if (code === 200) handleApiResponse(isEdit);
    else ElMessage.error(msg);
  } catch (error) {
    ElMessage.error("操作失败");
  } finally {
    loading.value = false;
  }
};

const resetForm = (formEl) => {
  if (!formEl) return;
  ruleFormRef.value.resetFields();
  dialogVisible.value = false;
};

const handleClose = (done: () => void) => {
  dialogVisible.value = false;
};

const resetChecked = () => {
  if (treeRef.value) {
    treeRef.value.setCheckedKeys([], false);
  }
  isAllChecked.value = false; // 重置全选状态
};

// 菜单树
const getTableData = async () => {
  const data = await listAll();
  if (data.data && data.data.length > 0) {
    // 将全选节点作为第一个节点
    treeRoleData.value = [selectAllNode.value, ...data.data];
  } else {
    // 即使没有数据，也显示全选节点
    treeRoleData.value = [selectAllNode.value];
  }

  // 重置全选状态
  isAllChecked.value = false;
};

// 修改全选处理逻辑
const handleTreeNodeClick = (data) => {
  // 处理全选节点点击
  if (data.id === "select-all") {
    toggleSelectAll();
    return;
  }
};
</script>

<template>
  <div class="page">
    <ElDialog
      v-model="dialogVisible"
      :title="title"
      width="600"
      :before-close="handleClose"
    >
      <div>
        <ElForm
          ref="ruleFormRef"
          :model="ruleForm"
          :rules="rules"
          label-width="120px"
        >
          <ElFormItem label="角色名称：" prop="roleName">
            <ElInput
              v-model="ruleForm.roleName"
              placeholder="请输入角色名称"
              style="width: 420px"
              @input="(value) => spaceInput('roleName', value)"
            />
          </ElFormItem>
          <ElFormItem label="角色标识：" prop="roleValue">
            <ElInput
              v-model="ruleForm.roleValue"
              placeholder="请输入角色标识"
              style="width: 420px"
              @input="(value) => spaceInput('roleValue', value)"
            />
          </ElFormItem>
          <ElFormItem label="排序：" prop="sort">
            <ElInputNumber
              v-model="ruleForm.sort"
              :min="1"
              :max="9999"
              controls-position="right"
              size="large"
              placeholder="请输入排序号"
              style="width: 420px"
            />
          </ElFormItem>
          <ElFormItem label="状态：" prop="status">
            <ElRadioGroup v-model="ruleForm.status" placeholder="请选择状态">
              <ElRadio value="1">启用</ElRadio>
              <ElRadio value="0">禁用</ElRadio>
            </ElRadioGroup>
          </ElFormItem>
          <ElFormItem label="菜单权限：" prop="menuIds">
            <ElTree
              :data="treeRoleData"
              ref="treeRef"
              :props="defaultProps"
              node-key="id"
              show-checkbox
              highlight-current
              default-expand-all
              style="width: 420px"
              @check="handleCheckChange"
              @node-click="handleTreeNodeClick"
            />
          </ElFormItem>
        </ElForm>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <ElButton @click="resetForm(ruleFormRef)">取消</ElButton>
          <ElButton
            type="primary"
            @click="() => submitForm(title !== '添加角色')"
            :loading="loading"
          >
            确定
          </ElButton>
        </div>
      </template>
    </ElDialog>
  </div>
</template>
<style scoped>
.el-tree {
  width: 100%;
  height: 170px;
  padding: 10px;
  overflow: scroll;
  background: #fff;
  border: 1px solid #dcdfe6;
  border-radius: 3px;
}

:deep(.el-input-number .el-input__inner) {
  text-align: left !important;
}

.el-tree {
  width: 100%;
  height: 170px;
  padding: 10px;
  overflow: scroll;
  background: #fff;
  border: 1px solid #dcdfe6;
  border-radius: 3px;
}

:deep(.el-input-number .el-input__inner) {
  text-align: left !important;
}

:deep(.el-tree-node.is-current > .el-tree-node__content) {
  background-color: #e6f7ff !important;
}
</style>
